/**
 * Copyright (c) 2017, Alex. All rights reserved.
 */
package com.oschina.bottle.mysql.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.oschina.bottle.mysql.DataSourceProperties;
import com.oschina.bottle.mysql.enums.Driver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.sql.SQLException;
import java.util.Collections;

/**
 * 辅助类
 * 
 * @author <a href="mailto:zhongchao@gegejia.com">zhong</a>
 * @version 1.0 2017/9/28
 * @since 1.0
 */
public class DBHelper
{
    public final static Logger logger = LoggerFactory.getLogger(DBHelper.class);

    private final static String URL    = "jdbc:mysql://%s/%s?" +
        "autoReconnect=true&useCompression=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false";

    public static DruidDataSource buildDataSource(DataSourceProperties dbProperties) {
        DruidDataSource dataSource = new DruidDataSource();

        Assert.hasText(dbProperties.getHost(), "the datasource host must not be empty");
        Assert.hasText(dbProperties.getName(), "the datasource name must not be empty");
        Assert.hasText(dbProperties.getUsername(), "the datasource username must not be empty");
        Assert.hasText(dbProperties.getPassword(), "the datasource password must not be empty");


        dataSource.setUrl(String.format(URL, dbProperties.getHost(), dbProperties.getName()));
        dataSource.setUsername(dbProperties.getUsername());
        dataSource.setPassword(dbProperties.getPassword());

        if(dbProperties.getHost().contains(",")) {
            dataSource.setDriverClassName(Driver.REPLICATION.getName());
        } else {
            dataSource.setDriverClassName(Driver.SINGLE.getName());
        }

        //以下为druid的优化参数
        dataSource.setMinIdle(dbProperties.getMinIdle());               //最小连接池数量
        dataSource.setMaxActive(dbProperties.getMaxActive());            //最大连接池数量
        dataSource.setMaxWait(dbProperties.getMaxWait());            //获取连接时的最大等待时间, 单位毫秒. 配置了maxWait后, 缺省启用公平锁, 并发效率会有所下降, 如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
        dataSource.setInitialSize(dbProperties.getInitialSize());
        //        dataSource.setPoolPreparedStatements(false);    //是否缓存preparedStatement, mysql下建议关闭
        //        dataSource.setMaxOpenPreparedStatements(-1);    //要启用PSSCache. 该配置必须大于0
        dataSource.setValidationQuery("SELECT 1");      //用于检测连接是否有效的sql
        dataSource.setValidationQueryTimeout(dbProperties.getValidationQueryTimeout());        //单位：秒，检测连接是否有效的超时时间
        dataSource.setTestOnBorrow(true);               //申请连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能。
        dataSource.setTestOnReturn(false);              //归还连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能
        dataSource.setTestWhileIdle(true);              //建议配置为true，不影响性能，并且保证安全性。
        dataSource.setMinEvictableIdleTimeMillis(dbProperties.getMinEvictableIdleTimeMillis());
        dataSource.setRemoveAbandonedTimeout(dbProperties.getRemoveAbandonedTimeout());
        dataSource.setConnectionInitSqls(Collections.singleton("set names utf8mb4"));

        try {
            dataSource.setFilters("stat");
            //            dataSource.setFilters("wall, stat");
            dataSource.setUseGlobalDataSourceStat(true);
            dataSource.init();
        } catch (SQLException e) {
            logger.error("load datasource error, dbProperties is :{}", e);
        }

        return dataSource;
    }
}
